/************************************************************************

								Heroes IV
					  Copyright 2000, The 3DO Company

	------------------------------------------------------------------
  							 transition_calculator.h

	$Header: /heroes4/transition_calculator.h $

	$NoKeywords: $

 ************************************************************************/

#ifndef TRANSITION_CALCULATOR_H_INCLUDED
#define TRANSITION_CALCULATOR_H_INCLUDED

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include "owned_ptr.h"
#include "uncopyable.h"
#include "screen_point.h"

class t_abstract_adventure_map;
class t_abstract_tile;
struct t_level_map_point_2d;
struct t_map_point_2d;
struct t_screen_point;
class t_transition_calculator;

// --------------------------------------------------------------------------
// Details namespace
// --------------------------------------------------------------------------

namespace transition_calculator_details
{

	// --------------------------------------------------------------------------
	// t_abstract_terrain_map class
	// --------------------------------------------------------------------------

	class t_abstract_terrain_map
	{
	public:
		// Member functions
		t_abstract_tile const &			get_const_tile( t_level_map_point_2d const & point ) const;
		virtual int						get_row_end( int row ) const = 0;
		virtual int						get_row_start( int row ) const = 0;
		virtual int						get_size() const = 0;
		virtual t_abstract_tile &		get_tile( t_level_map_point_2d const & point ) = 0;
		virtual t_abstract_tile const &	get_tile( t_level_map_point_2d const & point ) const = 0;
		virtual t_screen_point			get_view_size() const = 0;
		virtual bool					is_valid( t_map_point_2d const & point ) const = 0;
		virtual bool					is_valid( t_level_map_point_2d const & point ) const = 0;

	protected:
		// Destructor
		~t_abstract_terrain_map() {}
	};

	// --------------------------------------------------------------------------
	// --------------------------------------------------------------------------
	inline t_abstract_tile const & t_abstract_terrain_map::get_const_tile(
		t_level_map_point_2d const & point ) const
	{
		return get_tile( point );
	}

	// --------------------------------------------------------------------------
	// t_terrain_map_adapter class template
	// --------------------------------------------------------------------------

	template < typename t_adaptee >
	class t_terrain_map_adapter : public t_abstract_terrain_map
	{
	public:
		// Constructor
		explicit t_terrain_map_adapter( t_adaptee & adaptee );

		// Member functions
		virtual int						get_row_end( int row ) const;
		virtual int						get_row_start( int row ) const;
		virtual int						get_size() const;
		virtual t_abstract_tile &		get_tile( t_level_map_point_2d const & point );
		virtual t_abstract_tile const &	get_tile( t_level_map_point_2d const & point ) const;
		virtual t_screen_point			get_view_size() const;
		virtual bool					is_valid( t_map_point_2d const & point ) const;
		virtual bool					is_valid( t_level_map_point_2d const & point ) const;

	private:
		// Data members
		t_adaptee &		m_adaptee;
	};

	// --------------------------------------------------------------------------
	// t_terrain_map_adapter members
	// --------------------------------------------------------------------------

	// --------------------------------------------------------------------------
	// --------------------------------------------------------------------------
	template < typename t_adaptee >
	inline t_terrain_map_adapter< t_adaptee >::t_terrain_map_adapter( t_adaptee & adaptee )
		:	m_adaptee( adaptee )
	{
	}

	// --------------------------------------------------------------------------
	// --------------------------------------------------------------------------
	template < typename t_adaptee >
	int t_terrain_map_adapter< t_adaptee >::get_row_end( int row ) const
	{
		return m_adaptee.get_row_end( row );
	}

	// --------------------------------------------------------------------------
	// --------------------------------------------------------------------------
	template < typename t_adaptee >
	int t_terrain_map_adapter< t_adaptee >::get_row_start( int row ) const
	{
		return m_adaptee.get_row_start( row );
	}

	// --------------------------------------------------------------------------
	// --------------------------------------------------------------------------
	template < typename t_adaptee >
	int t_terrain_map_adapter< t_adaptee >::get_size() const
	{
		return m_adaptee.get_size();
	}

	// --------------------------------------------------------------------------
	// --------------------------------------------------------------------------
	template < typename t_adaptee >
	t_abstract_tile & t_terrain_map_adapter< t_adaptee >::get_tile( t_level_map_point_2d const & point )
	{
		return m_adaptee.get_tile( point );
	}

	// --------------------------------------------------------------------------
	// --------------------------------------------------------------------------
	template < typename t_adaptee >
	t_abstract_tile const & t_terrain_map_adapter< t_adaptee >::get_tile( t_level_map_point_2d const & point ) const
	{
		return const_cast< t_adaptee const & >( m_adaptee ).get_tile( point );
	}

	// --------------------------------------------------------------------------
	// --------------------------------------------------------------------------
	template < typename t_adaptee >
	t_screen_point t_terrain_map_adapter< t_adaptee >::get_view_size() const
	{
		return m_adaptee.get_view_size();
	}

	// --------------------------------------------------------------------------
	// --------------------------------------------------------------------------
	template < typename t_adaptee >
	bool t_terrain_map_adapter< t_adaptee >::is_valid( t_map_point_2d const & point ) const
	{
		return m_adaptee.is_valid( point );
	}

	// --------------------------------------------------------------------------
	// --------------------------------------------------------------------------
	template < typename t_adaptee >
	bool t_terrain_map_adapter< t_adaptee >::is_valid( t_level_map_point_2d const & point ) const
	{
		return m_adaptee.is_valid( point );
	}

} // Details namespace

// --------------------------------------------------------------------------
// t_transition_calculator class
// --------------------------------------------------------------------------

class t_transition_calculator : private t_uncopyable
{
public:
	// Constructor/Destructor
	t_transition_calculator();
	~t_transition_calculator();

	// Member functions
	template < typename t_terrain_map_arg >
	bool set_transitions( t_terrain_map_arg & map, t_level_map_point_2d const & point )
	{
		transition_calculator_details::t_terrain_map_adapter< t_terrain_map_arg > map_adapter( map );
		return do_set_transitions( map_adapter, point );
	}

private:
	// Types
	class t_impl;

	// Data members
	t_owned_ptr< t_impl >	m_impl_ptr;

	// Member functions
	bool	do_set_transitions(
				transition_calculator_details::t_abstract_terrain_map &	map,
				t_level_map_point_2d const &							point );
};

// --------------------------------------------------------------------------
// t_shroud_transition_calculator class
// --------------------------------------------------------------------------

class t_shroud_transition_calculator : private t_uncopyable
{
public:
	// Constructor/Destructor
	t_shroud_transition_calculator();
	~t_shroud_transition_calculator();

	// Member functions
	bool	set_transitions(
				t_abstract_adventure_map &		map,
				int								team_num,
				t_level_map_point_2d const &	point );

private:
	// Types
	class t_impl;

	// Data members
	t_owned_ptr< t_impl >	m_impl_ptr;
};

#endif // TRANSITION_CALCULATOR_H_INCLUDED
